home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 19.9 KB | 699 lines | [TEXT/CWIE] |
- /*
- File: SetupGL Main.c
-
- Contains: An example of the use of the SeupGL utility code. This sample builds a context and lets the user control
- the specifications on the fly, rebuilding the context when the request changes. Controls are:
-
- Left/right arrows: smaller or larger resolution context
-
- Up/down arrows: 32/16 bit pixel depth toggle
-
- left/right bracket: chnage requested screen down or up one
-
- w: go to windowed mode
-
- f: go to fullscreen mode
-
- Written by: Geoff Stahl
-
- Copyright: 1999 Apple Computer, Inc., All Rights Reserved
-
- Change History (most recent first):
-
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Appleās
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- <7> 3/21/00 ggs Removed grey region call from drag, not needed
- <6> 1/26/00 ggs Add preflight support, handle failure conditions throughout app
- better
- <5> 1/24/00 ggs fixed Apple menu selection, fixed aglfont texture row length
- problem, fixed suspend/resume, fixed update
- <4> 12/18/99 ggs Fix headers
- <3> 12/18/99 ggs Added window/fullscreen toggle support and error window
- <2> 11/28/99 ggs Standard toolbox application
- <1> 11/28/99 ggs Initial Add
- <6> 9/14/99 GGS Corrected buffer rect handling and cleaned up code
- <5> 7/14/99 GGS Fixed multi-monitor window centering
- <4> 7/13/99 GGS Add work around for over zealous checking in single buffer DSp context attributes
- <3> 7/5/99 GGS Now correctly handle multi-monitor (DSp front buffer for single device; Window on top of context for multiple devices)
- <2> 5/28/99 GGS Added better multi-monitor support, clean code, corrected blanking bug, added timing, correct pixel formats
- <1> ? ? Initial build
- */
-
-
- // system includes ----------------------------------------------------------
-
- #include <Devices.h>
- #include <Dialogs.h>
- #include <DriverServices.h>
- #include <Events.h>
- #include <LowMem.h>
- #include <TextEdit.h>
- #include <ToolUtils.h>
- #include <Windows.h>
-
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <gl.h>
-
- // project includes ---------------------------------------------------------
-
- #include "SetupGL.h"
-
- // prototypes ---------------------------------------------------------------
-
- void InitToolbox(void);
- Boolean SetUp (void);
- void DoMenu (SInt32 menuResult);
- void DoKey (SInt8 theKey, SInt8 theCode);
- void DoUpdate (void);
- void DoEvent (void);
- void CleanUp (void);
-
- void drawGL(AGLContext aglContext, pstructGLInfo pglInfo);
-
- void DrawFrameRate (GLuint fontList);
- void DrawContextInfo (GLuint fontList);
-
- void DrawPSringGL (Str255 pstrOut, GLuint fontList);
- void DrawCSringGL (char * cstrOut, GLuint fontList);
- GLuint BuildFontGL (AGLContext ctx, GLint fontID, Style face, GLint size);
- void DeleteFontGL (GLuint fontList);
-
-
- // statics/globals (internal only) ------------------------------------------
-
- // Menu defs
- enum
- {
- kNumRes = 10,
- kNumFreqs = 11,
-
- kMenuApple = 128,
- kMenuFile = 129,
-
- kAppleAbout = 1,
- kFileQuit = 1
- };
-
- enum
- {
- kForegroundSleep = 0,
- kBackgroundSleep = 32000
- };
-
- const RGBColor rgbWhite = { 0xFFFF, 0xFFFF, 0xFFFF };
-
- SInt32 gSleepTime = kForegroundSleep;
- Boolean gDone = false, gfFrontProcess = true;
-
- Point gapntResolution [kNumRes] = {{300, 400}, {384, 512}, {480, 640}, {600, 800}, {624, 832}, {768, 1024}, {870, 1152}, {1024, 1280}, {1200, 1600}, {1440, 1920}};
- short gResCurrent = 2;
- long gaFreq [kNumFreqs] = {56, 60, 65, 67, 72, 75, 76, 85, 90, 100, 120};
- short gFreqCurrent = 7;
- short gNumDevice = 0;
- char gstrMode [256] = "";
-
- structGLInfo glInfo;
- AGLDrawable aglDraw = 0;
- AGLContext aglContext = 0;
- DSpContextReference dspContext = 0;
- GLuint gFontList = 0;
-
- WindowPtr gpWindowError = NULL;
-
-
- // functions (internal/private) ---------------------------------------------
-
- void InitToolbox(void)
- {
- MenuHandle menu;
-
- MaxApplZone ();
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- qd.randSeed = TickCount();
-
- // Init Menus
- menu = NewMenu (kMenuApple, "\p\024"); // new apple menu
- InsertMenu (menu, 0); // add menu to end
- AppendResMenu(menu, 'DRVR');
-
- menu = NewMenu (kMenuFile, "\pFile"); // new menu
- InsertMenu (menu, 0); // add menu to end
- AppendMenu (menu, "\pQuit/Q"); // add items
-
- DrawMenuBar();
- }
-
- // --------------------------------------------------------------------------
-
- Boolean SetUp (void)
- {
- short i;
- short fNum;
-
- InitToolbox ();
-
- // we want a context and a drawable
- gNumDevice = 0; // main device (1 = next device, etc.)
- memset(&glInfo, 0, sizeof glInfo);
- glInfo.width = gapntResolution [gResCurrent].h; // width of drawable (screen width in full screen mode)
- glInfo.height = gapntResolution [gResCurrent].v; // height of drawable (screen height in full screen mode)
- glInfo.fSizeMust = false; // dspContext must be requested height (ignored in window mode)
- // Note: This basically determines whether or not displays will step down to allocate or fail
- glInfo.pixelDepth = 16; // requested pixel depth
- glInfo.fDepthMust = false; // pixel depth must be set (if false then curretn depth will be used if able)
- glInfo.fFullscreen = true; // use DSp to get fullscreen?
- glInfo.fAcceleratedMust = true; // must renderer be accelerated?
- glInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always required)
- glInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always required)
- glInfo.freq = gaFreq [gFreqCurrent]; // desired vertical refresh frquency in Hz (0 = any)
- glInfo.fmt = 0; // output pixel format
-
- i = 0;
- glInfo.aglAttributes [i++] = AGL_RGBA;
- glInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER;
- glInfo.aglAttributes [i++] = AGL_NO_RECOVERY;
- glInfo.aglAttributes [i++] = AGL_ACCELERATED;
- glInfo.aglAttributes [i++] = AGL_DEPTH_SIZE;
- glInfo.aglAttributes [i++] = 16;
- glInfo.aglAttributes [i++] = AGL_ALL_RENDERERS;
- glInfo.aglAttributes [i++] = AGL_NONE;
-
- if (PreflightGL (glInfo.fFullscreen))
- {
- BuildGL (&aglDraw, &aglContext, &dspContext, &gNumDevice, &glInfo);
- if (!aglDraw || !aglContext)
- DestroyGL (&aglDraw, &aglContext, &dspContext, &glInfo);
- }
-
- if (!aglDraw || !aglContext)
- {
- Rect rectWin = {100, 100, 200, 400};
- gpWindowError = (WindowPtr) NewCWindow (NULL, &rectWin, "\p", 0, kWindowFloatProc, (WindowPtr)-1, 0, 0);
- ShowWindow ((GrafPtr)gpWindowError);
- }
- else
- {
- GetFNum("\pMonaco", &fNum); // build font
- gFontList = BuildFontGL (aglContext, fNum, normal, 9);
- // set mode string
- sprintf (gstrMode, "%d: %d x %d x %d (%d Hz)", gNumDevice, glInfo.width, glInfo.height, glInfo.pixelDepth, glInfo.freq);
- }
- return true;
- }
-
- // --------------------------------------------------------------------------
-
- void DoMenu (SInt32 menuResult)
- {
- SInt16 theMenu;
- SInt16 theItem;
- Str255 daName;
- MenuRef theMenuHandle;
-
- theMenu = HiWord(menuResult);
- theItem = LoWord(menuResult);
- theMenuHandle = GetMenuHandle(theMenu);
-
- switch (theMenu)
- {
- case kMenuApple:
- switch (theItem)
- {
- case kAppleAbout:
- break;
- default:
- GetMenuItemText (theMenuHandle, theItem, daName);
- OpenDeskAcc(daName);
- break;
- }
- break;
- case kMenuFile:
- switch (theItem)
- {
- case kFileQuit:
- gDone = true;
- break;
- }
- break;
- }
- HiliteMenu(0);
- DrawMenuBar();
- }
-
- // --------------------------------------------------------------------------
-
- void DoKey (SInt8 theKey, SInt8 theCode)
- {
- #pragma unused (theCode)
- // up and down arrows change bit depth (stop at top and bottom)
- // right and left arrows change size (stop at top and bottom)
- // +(=) and - change frequency request
- // [ and ] cnage requested display device
-
- short fNum;
-
- // resolution
- if (theKey == '\35')
- {
-
- if (++gResCurrent == kNumRes)
- gResCurrent = 0;
- glInfo.width = gapntResolution [gResCurrent].h;
- glInfo.height = gapntResolution [gResCurrent].v;
- }
- else if (theKey == '\34')
- {
- if (--gResCurrent < 0)
- gResCurrent = (short) (kNumRes - 1);
- glInfo.width = gapntResolution [gResCurrent].h;
- glInfo.height = gapntResolution [gResCurrent].v;
- }
-
- // pixel depth
- if (theKey == '\36')
- {
- glInfo.pixelDepth = 32;
- }
- else if (theKey == '\37')
- {
- glInfo.pixelDepth = 16;
- }
-
- // frequency
- if (theKey == '=')
- {
-
- if (++gFreqCurrent == kNumFreqs)
- gFreqCurrent = 0;
- glInfo.freq = gaFreq [gFreqCurrent];
- }
- else if (theKey == '-')
- {
- if (--gFreqCurrent < 0)
- gFreqCurrent = (short) (kNumFreqs - 1);
- glInfo.freq = gaFreq [gFreqCurrent];
- }
-
- // device
- if (theKey == ']')
- gNumDevice++;
- else if (theKey == '[')
- gNumDevice--;
-
- // device
- if (theKey == 'w')
- glInfo.fFullscreen = false;
- else if (theKey == 'f')
- glInfo.fFullscreen = true;
-
- glInfo.fSizeMust = false; // dspContext must be requested height (ignored in window mode)
- glInfo.fDepthMust = false; // pixel depth must be set (if false then curretn depth will be used if able)
- glInfo.fAcceleratedMust = true; // must renderer be accelerated?
- glInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always required)
- glInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always required)
-
- // rebuild GL
- if (gpWindowError)
- {
- DisposeWindow ((WindowPtr)gpWindowError);
- gpWindowError = NULL;
- }
-
- DeleteFontGL (gFontList);
- DestroyGL (&aglDraw, &aglContext, &dspContext, &glInfo);
- {
- EventRecord theEvent;
- while (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL)) // get all the event to ensure icons are not moved
- {}
- }
-
- if (PreflightGL (glInfo.fFullscreen))
- {
- BuildGL (&aglDraw, &aglContext, &dspContext, &gNumDevice, &glInfo);
- if (!aglDraw || !aglContext)
- DestroyGL (&aglDraw, &aglContext, &dspContext, &glInfo);
- }
-
- if (!aglDraw || !aglContext)
- {
- Rect rectWin = {100, 100, 200, 400};
- gpWindowError = (WindowPtr) NewCWindow (NULL, &rectWin, "\p", 0, kWindowFloatProc, (WindowPtr)-1, 0, 0);
- ShowWindow ((GrafPtr)gpWindowError);
- }
- else
- {
- GetFNum("\pMonaco", &fNum); // build font
- gFontList = BuildFontGL (aglContext, fNum, normal, 9);
- // set mode string
- sprintf (gstrMode, "%d: %d x %d x %d (%d Hz)", gNumDevice, glInfo.width, glInfo.height, glInfo.pixelDepth, glInfo.freq);
- }
- DoUpdate ();
- }
-
- // --------------------------------------------------------------------------
-
- void DoUpdate (void)
- {
- if (aglDraw && aglContext)
- drawGL (aglContext, &glInfo);
- else
- {
- GrafPtr gpSave;
- GetPort (&gpSave);
- SetPort (gpWindowError);
- MoveTo (10, 20);
- DrawString ("\pBuildGL failed.");
- SetPort (gpSave);
- }
- }
-
- // --------------------------------------------------------------------------
-
- void DoEvent (void)
- {
- EventRecord theEvent;
- Rect rectGrow;
- SInt32 menuResult;
- WindowRef whichWindow;
- GrafPtr pGrafSave;
- long grow;
- SInt16 whatPart;
- SInt8 theKey;
- SInt8 theCode;
- Boolean fProcessed = false;
-
- if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL))
- {
- if (dspContext)
- DSpProcessEvent (&theEvent, &fProcessed);
- if (!fProcessed)
- {
- switch (theEvent.what)
- {
- case mouseDown:
- whatPart = FindWindow(theEvent.where, &whichWindow);
- switch (whatPart)
- {
- case inGoAway:
- break;
- case inMenuBar:
- DrawMenuBar();
- menuResult = MenuSelect(theEvent.where);
- if (HiWord(menuResult) != 0)
- DoMenu(menuResult);
- break;
- case inDrag:
- DragWindow (whichWindow, theEvent.where, NULL);
- break;
- case inGrow:
- SetRect (&rectGrow, 100, 100, 20000, 20000);
- grow = GrowWindow (whichWindow, theEvent.where, &rectGrow);
- if (grow)
- {
- SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true);
- // do content stuff here
- SetPort (whichWindow);
- InvalRect (&whichWindow->portRect); // redraw all
- }
- break;
- case inSysWindow:
- SystemClick(&theEvent, whichWindow);
- break;
- }
- break;
- case keyDown:
- case autoKey:
- theKey = theEvent.message & charCodeMask;
- theCode = (theEvent.message & keyCodeMask) >> 8;
- if ((theEvent.modifiers & cmdKey) != 0)
- {
- menuResult = MenuKey(theKey);
- if (HiWord(menuResult) != 0)
- DoMenu (menuResult);
- }
- else
- DoKey (theKey, theCode);
- break;
- case updateEvt:
- whichWindow = (WindowRef) theEvent.message;
- GetPort (&pGrafSave);
- SetPort ((GrafPtr) whichWindow);
- BeginUpdate(whichWindow);
- if ((CGrafPtr) whichWindow == aglDraw)
- DoUpdate();
- SetPort ((GrafPtr) whichWindow);
- EndUpdate(whichWindow);
- SetPort (pGrafSave);
- break;
- case diskEvt:
- break;
- case osEvt:
- if (theEvent.message & 0x01000000) // Suspend/resume event
- {
- if (theEvent.message & 0x00000001) // Resume
- {
-
- gSleepTime = kForegroundSleep;
- if (aglDraw && aglContext)
- {
- HideCursor ();
- ShowWindow ((WindowPtr) aglDraw);
- SelectWindow ((WindowPtr) aglDraw);
- ResumeGL (aglDraw, aglContext);
- }
- DoUpdate ();
- gfFrontProcess = true;
- }
- else
- {
- gSleepTime = kBackgroundSleep; // Suspend
- if (aglDraw && aglContext)
- {
- PauseGL (aglContext);
- HideWindow ((WindowPtr) aglDraw);
- ShowCursor ();
- }
- gfFrontProcess = false;
- }
- }
- break;
-
- case kHighLevelEvent:
- AEProcessAppleEvent(&theEvent);
- break;
- }
- }
- }
- else
- {
- if (gfFrontProcess)
- DoUpdate ();
- }
- }
-
- // --------------------------------------------------------------------------
-
- void CleanUp (void)
- {
- MenuHandle hMenu;
-
- DeleteFontGL (gFontList);
- DestroyGL (&aglDraw, &aglContext, &dspContext, &glInfo);
-
- if (gpWindowError)
- {
- DisposeWindow ((WindowPtr)gpWindowError);
- gpWindowError = NULL;
- }
-
- hMenu = GetMenuHandle (kMenuFile);
- DeleteMenu (kMenuFile);
- DisposeMenu (hMenu);
-
- hMenu = GetMenuHandle (kMenuApple);
- DeleteMenu (kMenuApple);
- DisposeMenu (hMenu);
- }
-
- // --------------------------------------------------------------------------
-
- int main (void)
- {
- if (SetUp ())
- while (!gDone)
- DoEvent ();
- CleanUp ();
- return 0;
- }
-
-
- #pragma mark -
- //-----------------------------------------------------------------------------------------------------------------------
-
- // OpenGL Drawing
-
- void drawGL(AGLContext aglContext, pstructGLInfo pglInfo)
- {
- static float f, s, c;
- GLboolean fState = GL_FALSE;
-
- f += 0.01;
- s = sin(f);
- c = cos(f);
-
- glClearColor(0.15f, 0.15f, 0.15f, 1.0f); // Clear color buffer to dark grey
- glClear(GL_COLOR_BUFFER_BIT);
-
- glBegin(GL_POLYGON); // Draw a smooth shaded polygon
- glColor3d(1.0, 0.0, 0.0);
- glVertex3d(s, c, 0.0);
- glColor3d(0.0, 1.0, 0.0);
- glVertex3d(-c, s, 0.0);
- glColor3d(0.0, 0.0, 1.0);
- glVertex3d(-s, -c, 0.0);
- glColor3d(0.7, 0.7, 0.7);
- glVertex3d(c, -s, 0.0);
- glEnd();
-
- // Draw frame rate (set color and position first)
- glColor3d(1.0, 1.0, 1.0);
- glRasterPos3d (-0.95, (pglInfo->height - 40.0) / (float) pglInfo->height, 0.0);
- DrawFrameRate (gFontList);
- glRasterPos3d (-0.95, (pglInfo->height - 65.0) / (float) pglInfo->height, 0.0);
- DrawContextInfo (gFontList);
-
- glRasterPos3d (-0.95, -(pglInfo->height - 45.0) / (float) pglInfo->height, 0.0);
- DrawCSringGL ((char*) glGetString (GL_VENDOR), gFontList);
- glRasterPos3d (-0.95, -(pglInfo->height - 20.0) / (float) pglInfo->height, 0.0);
- DrawCSringGL ((char*) glGetString (GL_RENDERER), gFontList);
-
- aglSwapBuffers(aglContext); // send swap command
- }
-
- //-----------------------------------------------------------------------------------------------------------------------
-
- // Draw frame rate in curent color at current raster positon with provided font display list
-
- void DrawFrameRate (GLuint fontList)
- {
- static char aChar[256] = "";
- static AbsoluteTime time = {0,0};
- static long frames = 0;
-
- AbsoluteTime currTime = UpTime ();
- float deltaTime = (float) AbsoluteDeltaToDuration (currTime, time);
-
- frames++;
-
- if (0 > deltaTime) // if negative microseconds
- deltaTime /= -1000000.0;
- else // else milliseconds
- deltaTime /= 1000.0;
- if (0.5 <= deltaTime) // has update interval passed
- {
- sprintf (aChar, "Swaps/Sec: %0.1f", frames / deltaTime);
- time = currTime; // reset for next time interval
- frames = 0;
- }
-
- DrawCSringGL (aChar, fontList);
- }
-
- //-----------------------------------------------------------------------------------------------------------------------
-
- // Draw height,width, bit pixel and frequency for context
-
- void DrawContextInfo (GLuint fontList)
- {
- DrawCSringGL (gstrMode, fontList);
- }
-
- #pragma mark -
- //-----------------------------------------------------------------------------------------------------------------------
-
- void DrawPSringGL (Str255 pstrOut, GLuint fontList)
- {
- GLint i;
- for (i = 1; i <= pstrOut[0]; i++)
- glCallList (fontList + pstrOut[i]);
- }
-
- //-----------------------------------------------------------------------------------------------------------------------
-
- void DrawCSringGL (char * cstrOut, GLuint fontList)
- {
- GLint i = 0;
- while (cstrOut [i])
- glCallList (fontList + cstrOut[i++]);
- }
-
- //-----------------------------------------------------------------------------------------------------------------------
-
- GLuint BuildFontGL (AGLContext ctx, GLint fontID, Style face, GLint size)
- {
- GLuint listBase = glGenLists (256);
- if (aglUseFont (ctx, fontID , face, size, 0, 256, (long) listBase))
- {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- return listBase;
- }
- else
- {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glDeleteLists (listBase, 256);
- return 0;
- }
- }
-
- //-----------------------------------------------------------------------------------------------------------------------
-
- void DeleteFontGL (GLuint fontList)
- {
- if (fontList)
- glDeleteLists (fontList, 256);
- }